Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

core/takserver/src/jvmAndroidMain/kotlin/org/meshtastic/core/takserver/TakCertLoader.kt fix/qr-error-correction (7b45f84f) Text, 6.93 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.core.takserver

Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787java.io.ByteArrayInputStream
Tff7b72import T7ee787java.security.KeyStore
Tff7b72import T7ee787java.security.cert.CertificateFactory
Tff7b72import T7ee787java.security.cert.X509Certificate
Tff7b72import T7ee787javax.net.ssl.KeyManagerFactory
Tff7b72import T7ee787javax.net.ssl.SSLContext
Tff7b72import T7ee787javax.net.ssl.TrustManagerFactory

T8b949e/**
* Loads the bundled TAK server certificates from the classpath and builds an [SSLContext] suitable for running a TLS
* TAK server with mutual TLS (mTLS).
*
* Bundled resources (under `tak_certs/` on the module classpath):
* - `server.p12` — PKCS#12 containing the server's identity (cert + private key). Used as the server's identity during
* the TLS handshake.
* - `client.p12` — PKCS#12 containing an example client identity, included in the exported data package so ATAK / iTAK
* have a certificate it can present.
* - `ca.pem` — PEM-encoded CA certificate used to validate the presented client certificate during mTLS. Only clients
* whose certificate chains back to this CA are accepted.
*
* The certificates and keys are identical to the iOS Meshtastic-Apple bundle, so the same exported data package works
* for both platforms with no re-import. The `.p12` containers MUST stay encoded with legacy PKCS#12 algorithms
* (SHA1/3DES bags, SHA1 MAC): Android 9 and older cannot parse PBES2/AES containers, which breaks ATAK import (#6567).
*/
Tff7b72internal Tff7b72object T56d364TakCertLoader Tb4b4b4{

Tff7b72private Tff7b72const Tff7b72val Te6edf3RESOURCE_SERVER_P12 Tff7b72= Ta5d6ff"Ta5d6fftak_certs/server.p12Ta5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3RESOURCE_CLIENT_P12 Tff7b72= Ta5d6ff"Ta5d6fftak_certs/client.p12Ta5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3RESOURCE_CA_PEM Tff7b72= Ta5d6ff"Ta5d6fftak_certs/ca.pemTa5d6ff"

Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3cachedSslContextTb4b4b4: Te6edf3SSLContext? Tff7b72= Tff7b72null

Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3cachedServerP12Tb4b4b4: Te6edf3ByteArray? Tff7b72= Tff7b72null

Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3cachedClientP12Tb4b4b4: Te6edf3ByteArray? Tff7b72= Tff7b72null

Tf0883e@Volatile Tff7b72private Tff7b72var Te6edf3cachedCaPemTb4b4b4: Te6edf3ByteArray? Tff7b72= Tff7b72null

T8b949e/**
* Build (and cache) an [SSLContext] for the TAK server.
*
* The context uses the bundled `server.p12` for its identity and the bundled `ca.pem` to validate client
* certificates during mTLS. If anything fails to load (missing resources, bad password, corrupt keystore) this
* returns `null` and callers should fall back to a non-TLS listener or refuse to start.
*/
Tf0883e@Synchronized
Tff7b72fun Td2a8ffgetServerSslContextTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3SSLContext? Tb4b4b4{
Te6edf3cachedSslContextTff7b72?.Te6edf3let Tb4b4b4{
Tff7b72return Tffa657it
Tb4b4b4}
Tff7b72return Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3serverP12 Tff7b72=
Te6edf3loadResourceBytesTb4b4b4(Te6edf3RESOURCE_SERVER_P12Tb4b4b4) Tff7b72?: Te6edf3errorTb4b4b4(Ta5d6ff"Ta5d6ffBundled Tffd700$Te6edf3RESOURCE_SERVER_P12Ta5d6ff not found on classpathTa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3caPem Tff7b72= Te6edf3loadResourceBytesTb4b4b4(Te6edf3RESOURCE_CA_PEMTb4b4b4) Tff7b72?: Te6edf3errorTb4b4b4(Ta5d6ff"Ta5d6ffBundled Tffd700$Te6edf3RESOURCE_CA_PEMTa5d6ff not found on classpathTa5d6ff"Tb4b4b4)

T8b949e// Load the server identity (cert + private key).
Tff7b72val Te6edf3serverKeyStore Tff7b72=
Te6edf3KeyStoreTb4b4b4.Te6edf3getInstanceTb4b4b4(Ta5d6ff"Ta5d6ffPKCS12Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3ByteArrayInputStreamTb4b4b4(Te6edf3serverP12Tb4b4b4)Tb4b4b4.Te6edf3use Tb4b4b4{ Te6edf3input Tff7b72-Tff7b72>
Te6edf3loadTb4b4b4(Te6edf3inputTb4b4b4, Te6edf3TAK_BUNDLED_CERT_PASSWORDTb4b4b4.Te6edf3toCharArrayTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3kmf Tff7b72=
Te6edf3KeyManagerFactoryTb4b4b4.Te6edf3getInstanceTb4b4b4(Te6edf3KeyManagerFactoryTb4b4b4.Te6edf3getDefaultAlgorithmTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Tff7b72initTb4b4b4(Te6edf3serverKeyStoreTb4b4b4, Te6edf3TAK_BUNDLED_CERT_PASSWORDTb4b4b4.Te6edf3toCharArrayTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

T8b949e// Load the CA certificate(s) used to verify incoming client certs.
Tff7b72val Te6edf3caCerts Tff7b72= Te6edf3parsePemCertificatesTb4b4b4(Te6edf3caPemTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3caCertsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Te6edf3errorTb4b4b4(Ta5d6ff"Ta5d6ffNo certificates found inside Tffd700$Te6edf3RESOURCE_CA_PEMTa5d6ff"Tb4b4b4)
Tff7b72val Te6edf3trustKeyStore Tff7b72=
Te6edf3KeyStoreTb4b4b4.Te6edf3getInstanceTb4b4b4(Te6edf3KeyStoreTb4b4b4.Te6edf3getDefaultTypeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3loadTb4b4b4(Tff7b72nullTb4b4b4, Tff7b72nullTb4b4b4)
Te6edf3caCertsTb4b4b4.Te6edf3forEachIndexed Tb4b4b4{ Te6edf3indexTb4b4b4, Te6edf3cert Tff7b72-Tff7b72> Te6edf3setCertificateEntryTb4b4b4(Ta5d6ff"Ta5d6fftak-client-ca-Tffd700$Te6edf3indexTa5d6ff"Tb4b4b4, Te6edf3certTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3tmf Tff7b72=
Te6edf3TrustManagerFactoryTb4b4b4.Te6edf3getInstanceTb4b4b4(Te6edf3TrustManagerFactoryTb4b4b4.Te6edf3getDefaultAlgorithmTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Tff7b72initTb4b4b4(Te6edf3trustKeyStoreTb4b4b4) Tb4b4b4}

Tff7b72val Te6edf3sslContext Tff7b72= Te6edf3SSLContextTb4b4b4.Te6edf3getInstanceTb4b4b4(Ta5d6ff"Ta5d6ffTLSv1.2Ta5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Tff7b72initTb4b4b4(Te6edf3kmfTb4b4b4.Te6edf3keyManagersTb4b4b4, Te6edf3tmfTb4b4b4.Te6edf3trustManagersTb4b4b4, Tff7b72nullTb4b4b4) Tb4b4b4}

Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffTAK: loaded bundled TLS server identity and Tffd700${Te6edf3caCertsTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff CA certificate(s)Ta5d6ff" Tb4b4b4}
Te6edf3cachedSslContext Tff7b72= Te6edf3sslContext
Te6edf3sslContext
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3ThrowableTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffTAK: failed to build SSLContext from bundled certificates: Tffd700${Te6edf3eTb4b4b4.Te6edf3messageTffd700}Ta5d6ff" Tb4b4b4}
Tff7b72null
Tb4b4b4}
Tb4b4b4}

T8b949e/** Returns the raw bytes of the bundled `server.p12`. Used by the data package generator. */
Tf0883e@Synchronized
Tff7b72fun Td2a8ffgetServerP12BytesTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ByteArray? Tb4b4b4{
Te6edf3cachedServerP12Tff7b72?.Te6edf3let Tb4b4b4{
Tff7b72return Tffa657it
Tb4b4b4}
Tff7b72val Te6edf3bytes Tff7b72= Te6edf3loadResourceBytesTb4b4b4(Te6edf3RESOURCE_SERVER_P12Tb4b4b4)
Te6edf3cachedServerP12 Tff7b72= Te6edf3bytes
Tff7b72return Te6edf3bytes
Tb4b4b4}

T8b949e/** Returns the raw bytes of the bundled `client.p12`. Used by the data package generator. */
Tf0883e@Synchronized
Tff7b72fun Td2a8ffgetClientP12BytesTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ByteArray? Tb4b4b4{
Te6edf3cachedClientP12Tff7b72?.Te6edf3let Tb4b4b4{
Tff7b72return Tffa657it
Tb4b4b4}
Tff7b72val Te6edf3bytes Tff7b72= Te6edf3loadResourceBytesTb4b4b4(Te6edf3RESOURCE_CLIENT_P12Tb4b4b4)
Te6edf3cachedClientP12 Tff7b72= Te6edf3bytes
Tff7b72return Te6edf3bytes
Tb4b4b4}

T8b949e/** Returns the raw bytes of the bundled `ca.pem`. */
Tf0883e@Synchronized
Tff7b72fun Td2a8ffgetCaPemBytesTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ByteArray? Tb4b4b4{
Te6edf3cachedCaPemTff7b72?.Te6edf3let Tb4b4b4{
Tff7b72return Tffa657it
Tb4b4b4}
Tff7b72val Te6edf3bytes Tff7b72= Te6edf3loadResourceBytesTb4b4b4(Te6edf3RESOURCE_CA_PEMTb4b4b4)
Te6edf3cachedCaPem Tff7b72= Te6edf3bytes
Tff7b72return Te6edf3bytes
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffloadResourceBytesTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3ByteArray? Tb4b4b4{
Tff7b72val Te6edf3stream Tff7b72= Te6edf3TakCertLoaderTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4.Te6edf3classLoaderTff7b72?.Te6edf3getResourceAsStreamTb4b4b4(Te6edf3nameTb4b4b4) Tff7b72?: Tff7b72return Tff7b72null
Tff7b72return Te6edf3streamTb4b4b4.Te6edf3use Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3readBytesTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}

T8b949e/**
* Parse every `-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----` block in the given PEM bytes into
* [X509Certificate]s. Tolerates multiple certs in one file.
*/
Tff7b72private Tff7b72fun Td2a8ffparsePemCertificatesTb4b4b4(Te6edf3pemTb4b4b4: Te6edf3ByteArrayTb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3X509CertificateTff7b72> Tb4b4b4{
Tff7b72val Te6edf3factory Tff7b72= Te6edf3CertificateFactoryTb4b4b4.Te6edf3getInstanceTb4b4b4(Ta5d6ff"Ta5d6ffX.509Ta5d6ff"Tb4b4b4)
T8b949e// CertificateFactory.generateCertificates handles PEM bundles directly on all
T8b949e// standard Java providers, so we don't need to split ourselves.
Tff7b72return Te6edf3ByteArrayInputStreamTb4b4b4(Te6edf3pemTb4b4b4)Tb4b4b4.Te6edf3use Tb4b4b4{ Te6edf3input Tff7b72-Tff7b72>
Te6edf3factoryTb4b4b4.Te6edf3generateCertificatesTb4b4b4(Te6edf3inputTb4b4b4)Tb4b4b4.Te6edf3filterIsInstanceTff7b72<Te6edf3X509CertificateTff7b72>Tb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.06s